Daily Knowledge Drop
Coming with .NET 7, the MemoryCacheStatistics class, accessed through IMemoryCache.GetCurrentStatistics can provider useful statistics regarding the state of the memory cache. These include:
- how many items are currently in the cache
 - the current estimate size of the cache
 - the number of times the cache has been queried for a value, and the value was not present (misses)
 - the number of times the cache has been queried for a value, and the value was present (hits)
 
These stats can be leveraged to better understand how/if the cache mechanism is correctly configured and being used optimally.
Cache configuration
The first step is to register the require cache implementation instances with the dependency injection container. This is done using the AddMemoryCache extension method:
builder.Services
    .AddMemoryCache(memCacheOptions => 
        { 
            memCacheOptions.TrackStatistics = true; 
            memCacheOptions.SizeLimit = 1024; 
        });
- For stats to be tracked, the 
MemoryCacheOptions.TrackStatisticsvalue (memCacheOptions.TrackStatistics in the above example) needs to be set totrue - For the 
EstimateSizeproperty of the statistics to be tracked, the cache needs to have a SizeLimit specified. The SizeLimit does not represent memory size, but number of units - in the above example, the limit has been set to 1024 units, and when items are added to the cache one byte will be treated as a unit (this is not a required, its up to the developer to decide how many "units" each item added to the cache is worth) 
Cache usage
Set values
Now that the cache is configured, the next step is to start using it to store values. A simple getnumber endpoint is defined, which will return the number passed in:
- if the number does not exist in the cache, it will be added to the cache and returned
 - if the number already exists in the cache, it will be returned from the cache
 
// get the number from the route
// get the IMemoryCache from the DI container
app.MapGet("/getnumber/{number}", ([FromRoute]int number, 
    [FromServices] IMemoryCache cache) =>
{
    // first check the cache to see if the number
    // exists there
    if(cache.TryGetValue(number, out var value))
    {
        return $"'{value}' retrieved from cache";
    }
    // if it didn't exist, add it to the cache
    cache.Set(number, number, new MemoryCacheEntryOptions { Size = sizeof(int)});
    // return
    return $"'{number}' added to cache";
});
Invoking the endpoint with a number for the first time /getnumber/1, will result in:
'1' added to cache
While invoking subsequent times with the same number will result in:
'1' retrieved from cache
The cache has been configured and the endpoint called a number of times, with unique and duplicate numbers, so next let's have a look at the stats.
Get statistics
To get a snapshot of the IMemoryCache statistics, the GetCurrentStatistics method is used:
app.MapGet("/getstats", ([FromServices] IMemoryCache cache) =>
{
    return cache.GetCurrentStatistics();
});
A sample return snapshot:
{
    "currentEntryCount":6,
    "currentEstimatedSize":24,
    "totalMisses":6,
    "totalHits":2
}
In this example:
6 items have been addedto the cache- the 6 items take up 
24 of the available 1024 unitsavailable (6 x 4 bytes) - the cache has been checked and did 
not contain the queried value 6 times - the cache has been checked and 
did contain the queried value twice 
Notes
This information is very valuable and can be leveraged to confirm if the cache configured for an application is successfully being used - over time, one would want to see a high number of hits and relatively low number of misses. This information can be used to determine if the cache strategy needs to be modified (cache based on a different key) or maybe increase or decrease the cache size.
References
IMemoryCache.GetCurrentStatistics Method
Daily Drop 183: 17-10-2022
At the start of 2022 I set myself the goal of learning one new coding related piece of knowledge a day.
It could be anything - some.NET / C# functionality I wasn't aware of, a design practice, a cool new coding technique, or just something I find interesting. It could be something I knew at one point but had forgotten, or something completely new, which I may or may never actually use.
The Daily Drop is a record of these pieces of knowledge - writing about and summarizing them helps re-enforce the information for myself, as well as potentially helps others learn something new as well.